<template>
  <div id="app">
    <h2>canvas 组件画板</h2>
    <div class="canvas-container">
      <div class="canvas-item">
        <div class="title">条形进度条</div>
        <canvas id="canvas1" width="450" height="16"></canvas>
		    <iy-input size="mini" placeholder="小于1的数" @change="(e) => initCanvas1((!isNaN(Number(e)) && Number(e) <= 1) ? Number(e) : 0)"></iy-input>
      </div>
      <div class="canvas-item">
        <div class="title">环形进度条</div>
        <div class="canvas2-container">
          <canvas id="canvas2" width="300" height="300" style="width: 100%"></canvas>
        </div>
        <iy-input size="mini" placeholder="小于1的数" @change="(e) => initCanvas2((!isNaN(Number(e)) && Number(e) <= 1) ? Number(e) : 0)"></iy-input>
      </div>
      <div class="canvas-item">
        <div class="title">刮刮卡</div>
        <div class="canvas3-container">
          <span>{{reward}}</span>
          <canvas id="canvas3" width="500" height="300" style="width: 100%"></canvas>
        </div>
        <iy-button @click="resetCanvas3" style="margin-left: 10px;">重置</iy-button>
      </div>
      <div class="canvas-item">
        <div class="title">柱状图表</div>
        <div class="canvas4-container">
          <canvas id="canvas4" width="1000" height="520" style="width: 100%;"></canvas>
          <div class="bg"></div>
        </div>
        <div style="width: 30px;">
          <p>x: {{currentData.xAxis}}</p>
          <p>y: {{currentData.value}}</p>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: "App",
  data() {
    return {
      reward: '锅盖一顶',
      data: [
        {xAxis:'2012',value:2141},
        {xAxis:'2013',value:1499},
        {xAxis:'2014',value:3260},
        {xAxis:'2015',value:1170},
        {xAxis:'2016',value:970},
        {xAxis:'2017',value:2350}
      ],
      currentData: {},
      yEqual: 5 //y轴分成几等份
    }
  },
  mounted() {
    this.initCanvas1(0.5)
    this.initCanvas2(0.5)
    this.initCanvas3()
    this.initCanvas4()
  },
  methods: {
    resetCanvas3(){
      const rewardList = ['锅盖一顶', '草原帽一顶', '十全大补丸一粒', '耳刮子一打', '送你离开', '想中奖吗骚年', '可以下车了']
      this.reward = rewardList[Math.floor(Math.random() * 7)]
      let canvas = document.getElementById("canvas3")
      let ctx = canvas.getContext("2d")
      ctx.fillStyle = '#999'
      ctx.globalCompositeOperation = "source-over"
      ctx.fillRect(0, 0, 500, 300)
    },
    getYFictitiousCanvas4(data) {
        let arr = data.slice(0)
        arr.sort(function(a,b){
            return -(a.value-b.value)
        })
        let len = Math.ceil(arr[0].value / this.yEqual)
        let pow = len.toString().length - 1
        pow = pow > 2 ? 2 : pow
        return Math.ceil(len / Math.pow(10,pow)) * Math.pow(10,pow)
    },
    initCanvas1(percent = 1) {
      let canvas = document.getElementById("canvas1")
      let ctx = canvas.getContext("2d")
      ctx.clearRect(0, 0, 450, 16)

      let sumWidth = 392
      
      ctx.beginPath()
      ctx.lineCap = 'round'
      ctx.lineWidth = 8
      ctx.strokeStyle = '#ddd'
      ctx.moveTo(4, 8)
      ctx.lineTo(sumWidth, 8)
      ctx.stroke()
      ctx.closePath()

      let current = 0
      draw()

      function draw() {
        if (current < percent * sumWidth) {
          ctx.clearRect(0, 0, current + 4, 16)
          ctx.clearRect(400, 0, 50, 16)
          ctx.beginPath()
          ctx.lineCap = 'round'
          ctx.strokeStyle = '#4262ff'
          ctx.moveTo(4, 8)
          ctx.lineTo(current + 4, 8)
          ctx.stroke()
          ctx.closePath()
          ctx.font = "16px sans-serif"
          ctx.fillStyle = '#4262ff'
          ctx.fillText(Math.ceil(current / sumWidth * 100) + '%', 400, 14)
          current = current + 2
          setTimeout(() => {
            draw()
          }, 5)
        }
      }
    },
    initCanvas2(percent = 1) {
      let canvas = document.getElementById("canvas2")
      let ctx = canvas.getContext("2d")

      let current = 0
      draw(current)
      function drawBg() {
        ctx.beginPath()
        ctx.lineCap = 'round'
        ctx.lineWidth = 20
        ctx.strokeStyle = '#ddd'
        ctx.arc(150, 150, 130, 0, 2 * Math.PI, false)
        ctx.stroke()
        ctx.closePath()
      }
      function draw(deg) {
        ctx.clearRect(0, 0, 300, 300)
        drawBg()
        ctx.beginPath()
        ctx.lineCap = 'round'
        ctx.strokeStyle = '#4262ff'
        ctx.arc(150, 150, 130, Math.PI * 3 / 2, Math.PI * 3 / 2 + Math.PI / 180 * deg, false)
        ctx.stroke()
        ctx.closePath()
        ctx.font = "32px sans-serif"
        ctx.fillStyle = '#4262ff'
        ctx.fillText(Math.ceil(current / 360 * 100) + '%', 120, 160)
        current = current + 1
        if (current <= percent * 360) {
          setTimeout(() => {
            draw(current)
          }, 5)
        }
      }
    },
    initCanvas3(){
      let state = false
      let canvas = document.getElementById("canvas3")
      let ctx = canvas.getContext("2d")
      ctx.fillStyle = '#999'
      ctx.fillRect(0, 0, 500, 300)
      ctx.fillStyle = '#666'
      ctx.font = '50px sans-serif'
      ctx.fillText('刮开可开奖', canvas.width / 2 - 120, canvas.height / 2 + 20)
      ctx.globalCompositeOperation = "destination-out"
      canvas.onmousemove = (e) => {
        if(!state) return
        let event = e || window.event
        let x = event.clientX - canvas.getBoundingClientRect().left
        let y = event.clientY - canvas.getBoundingClientRect().top
        //用canvas.offsetParent 可得到元素是相对于哪个元素定位的 如果是相对于body定位则可以使用canvas.offsetTop 与event.pageY 得到鼠标相对于canvas区域的位置
        ctx.beginPath()
        ctx.moveTo(x, y)
        ctx.globalCompositeOperation = "destination-out"
        ctx.arc(x * 2, y * 2, 30, 0, Math.PI * 2, false) //注意要除2 因为为了保证画板清晰度 画板扩大了两倍
        ctx.fill()
        ctx.closePath()
        //当所有判断透明度的值有百分之60之上,就清空画布,将刮奖区完全显示出来
        //图像的每个点的像素值,四个为一组,分别代表rgba
        let imgData = ctx.getImageData(0, 0, canvas.width, canvas.height)//获取画布中的所有像素
        let data = imgData.data //得到像素的字节数据
        let length = data.length //获取该数据的长度
        let transparent = 0 //设置一个变量来记录已经变为透明的像素点的数量
        for (let i = 0; i < length; i += 4) { //循环遍历每一个像素
          let alpha = data[i + 3] //获取每个像素的透明度数值
          if (alpha < 10) //当透明度小于10时，认为它已经被擦除，transparent数值加1
            transparent++
        }
        let percentage = transparent / (length / 4) //计算透明像素在所有像素点中所占比例
        if (percentage > 0.55) //当比例大于90%时，显示刮奖结束字样
          ctx.clearRect(0, 0, canvas.width, canvas.height)
      }
      canvas.onmousedown = () => {
        state = true
      }
      canvas.onmouseup = () => {
        state = false
      }
    },
    initCanvas4(){
      let canvas = document.getElementById("canvas4")
      let ctx = canvas.getContext("2d")
      let width = canvas.width
      let height = canvas.height
      let padding = 100       // 坐标轴到canvas边框的边距，留边距写文字

      //画坐标轴
      ctx.beginPath()
      ctx.lineWidth = 1
      // y轴线
      ctx.moveTo(padding + 0.5, height - padding + 0.5)
      ctx.lineTo(padding + 0.5, padding + 0.5)
      ctx.stroke()
      // x轴线
      ctx.moveTo(padding + 0.5, height - padding + 0.5)
      ctx.lineTo(width - padding + 0.5, height - padding + 0.5)
      ctx.stroke()

      //画坐标点
      let yNumber = 5                                             // y轴的段数
      let yLength = Math.floor((height - padding * 2) / yNumber)  // y轴每段的真实长度
      let xLength = Math.floor((width - padding * 2) / this.data.length)  // x轴每段的真实长度

      ctx.beginPath()
      ctx.textAlign = 'center'
      ctx.fillStyle = '#000000'
      ctx.strokeStyle = '#000000'

      // x轴刻度和值
      for (let i = 0; i < this.data.length; i++) {
          let xAxis = this.data[i].xAxis
          let xlen = xLength * (i + 1)
          ctx.moveTo(padding + xlen, height - padding)
          ctx.lineTo(padding + xlen, height - padding + 5)
          ctx.stroke()     
          ctx.font = "20px sans-serif"                                  // 画轴线上的刻度
          ctx.fillText(xAxis, padding + xlen - xLength / 2, height - padding + 30)   // 填充文字
      }
      // y轴刻度和值
      for (let i = 0; i < yNumber; i++) {
          let y = this.getYFictitiousCanvas4(this.data) * (i + 1)
          let ylen = yLength * (i + 1)
          ctx.moveTo(padding, height - padding - ylen)
          ctx.lineTo(padding - 5, height - padding - ylen)
          ctx.stroke()
          ctx.font = "20px sans-serif"
          ctx.fillText(y, padding - 40, height - padding - ylen + 5)
      }

      let looped = null
      let current = 0
      function looping() {
          looped = requestAnimationFrame(looping)
          if(current < 100){      
          // current 用来计算当前柱状的高度占最终高度的百分之几，通过不断循环实现柱状上升的动画
              current = (current + 3) > 100 ? 100 : (current + 3)
              drawAnimation()
          }else{
              window.cancelAnimationFrame(looped)
              looped = null
          }
      }
      const drawAnimation = () => {
          let yRatio = yLength / this.getYFictitiousCanvas4(this.data)
          for(let i = 0; i < this.data.length; i++) {
              let x = Math.ceil(this.data[i].value * current / 100 * yRatio)
              let y = height - padding - x
              ctx.fillStyle = '#4262ff'
              ctx.fillRect(padding + xLength * (i + 0.25), y, xLength/2, x)
              // 保存每个柱状的信息
              this.data[i].left = padding + xLength / 4 + xLength * i
              this.data[i].top = y
              this.data[i].right = padding + 3 * xLength / 4 + xLength * i
              this.data[i].bottom = height - padding
          }
      }
      looping()
      canvas.addEventListener('mousemove',(e) => {
          let ev = e || window.event
          for (let i=0;i<this.data.length;i++){
              for (let i=0;i<this.data.length;i++){
                  if(ev.offsetX * 2 > this.data[i].left &&
                  ev.offsetX * 2 < this.data[i].right &&
                  ev.offsetY * 2 > this.data[i].top &&
                  ev.offsetY * 2 < this.data[i].bottom){
                      // console.log('我在第'+i+'个柱状里。');
                      this.currentData = this.data[i]
                      ctx.fillStyle = '#ccc'
                      ctx.globalCompositeOperation = 'destination-over'
                      ctx.fillRect(padding + xLength * (i + 0.25) - 20, padding, xLength/2 + 40, height - padding * 2)
                  }
              }
          }
      })
    }
  }
};
</script>

<style lang="less">
#app {
  font-family: "Avenir", Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  .canvas-container {
    width: 1200px;
    height: 600px;
    margin: 0 auto;
    border: 1px solid lightblue;
    display: flex;
    flex-wrap: wrap;
    box-sizing: border-box;
    .canvas-item {
      width: 50%;
      height: 50%;
      box-sizing: border-box;
      border: 1px dashed lightblue;
      position: relative;
      overflow: hidden;
      display: flex;
      align-items: center;
      justify-content: center;
      .title {
        position: absolute;
        top: -44px;
        left: 0;
        width: 100%;
        padding: 14px 0;
        line-height: 16px;
        background: #2c3e50;
        color: white;
        font-weight: bold;
        transition: top 0.2s linear;
      }
      &:hover {
        .title {
          top: 0;
          transition: top 0.2s linear;
        }
      }
      .canvas2-container{
        width: 150px;
        height: 150px;
      }
      .canvas3-container{
        width: 250px;
        height: 150px;
        // position: relative;
        display: flex;
        justify-content: center;
        align-items: center;
        span{
          position: absolute;
          font-size: 30px;
          font-weight: bold;
          z-index: -1;
        }
      }
      .canvas4-container{
        width: 500px;
        height: 260px;
        position: relative;
        .bg{
          position: absolute;
          background: #ccc;
        }
      }
    }
  }
}
</style>
